package elements;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.Random;

import scaler.Scaler;

import mover.GameMover;

public class GameCharacter extends GameElement {
	public static final String RANDOM_CHAR = "\0";
	public static final int RANDOM_REFRESH = -1;
	public static final int NO_REFRESH = 0;
	private int fontSize = 21, height = 0, width = 0;
	private Font font;
	private FontMetrics metrics = null;
	
	/**
	 * The character which will be painted
	 * '\0' means random character
	 * 
	 * '\0' is default
	 */
	private String str;
	
	public GameCharacter(GameMover mover, Scaler scaler, String c) {
		super(mover, scaler);
		this.str = c;
		this.font = new Font ("Calibri", 1, scaler.calcY(fontSize));
		
		// Approximates the height and width
		this.height = fontSize/2; this.width = str.length()*2;

		// Randomvariables
		if(c.equals(RANDOM_CHAR)) {
			this.str = "" + getRandomChar();
		}
	}
	
	/**
	 * Will set c = randomChar
	 * and will use no refresh
	 */
	public GameCharacter() {
		super(NO_MOVEMENT, Scaler.NO_SCALING);
		this.str = "" + getRandomChar();
	}
	
	/*@Override
	public void update() {
		super.update();
		//timesaver
		if(refresh == 0) return;
		
		if(getCount() % refresh == 0) {
			// New character
			if(randomChar) str = "" + getRandomChar();
			// New color
			setRandomColor();
			
			// New timer
			if(randomRefresh) refresh = getRandomRefreshTimer();
		}
	}
*/
	@Override
	public void reset() {
		super.reset();
		// Character
		str = "" + getRandomChar();
	}

	@Override
	public void paint(Graphics g) {
		if(trans == NOT_VISIBLE) return;
		
		updateFontSize();
		if(metrics == null) {
			metrics = g.getFontMetrics(font);
			width = metrics.stringWidth(str);
			height =  metrics.getAscent() - metrics.getLeading();
		}
		
		g.setColor(transparentColor());
		g.setFont(font);
		g.drawString(""+this.str, getMovedX(), getMovedY()+height);
	}
	
	/**
	 * @return a character between 0-9 or A-Z
	 */
	public static char getRandomChar() {
		int min = 0, max = 0;
		
		if(random.nextBoolean()) {
			// char = 0 to 9
			// ASCII values
			min = 48;
			max = 58;
		} else {
			// char = A to Z
			// ASCII values
			min = 65;
			max = 90;
		}
		
		return (char) (random.nextInt(max - min) + min);
	}
	
	/**
	 * Returns a random character, except the given one
	 * @param c
	 * @return
	 */
	public static char getRandomChar(char c) {
		int min = 0, max = 0;
		
		if(random.nextBoolean()) {
			// char = 0 to 9
			// ASCII values
			min = 48;
			max = 58;
		} else {
			// char = A to Z
			// ASCII values
			min = 65;
			max = 90;
		}
		
		int ret = (random.nextInt(max - min) + min);
		// If randomly the given char was choosen
		if(ret == (int) c) {
			if(ret <= (min+1) || (ret < (max-1) && random.nextBoolean())) {
				++ret;
				ret += random.nextInt(max - ret);
			} else {
				--ret;
				ret -= random.nextInt(ret - min);
			}
		}
		return (char) ret;
	}
	
	private void updateFontSize(){
		if(scaler.calcY(fontSize) != font.getSize()){
			setFontSize(fontSize);
		}
	}
	
	public void setFontSize(int size) {
		fontSize = size;
		this.font = font.deriveFont((float)scaler.calcY(fontSize));
		metrics = null;
		
		// Approximate the size
		this.height = size/2; this.width = str.length() * (size / 2); 
	}
	
	public void calcSize(Graphics g) {
		metrics = g.getFontMetrics(font);
		width = metrics.stringWidth(str);
		height =  metrics.getAscent() - metrics.getLeading();
	}

	@Override
	public int getWidth() {
		return width;
	}
	@Override
	public int getScaledWidth() {
		return width;
	}

	@Override
	public int getHeight() {
		return height;
	}
	@Override
	public int getScaledHeight() {
		return height;
	}
	
	@Override
	public String toString() {
		return str;
	}
	
	public void setString(String s) {
		this.str = s;
	}
	
	public char getChar() {
		if(str.length() == 1) {
			return (str.charAt(0));
		} 
		return '\0';
	}

	@Override
	public GameCharacter clone() throws CloneNotSupportedException {
		GameCharacter clone = new GameCharacter(this.mover.clone(), this.scaler, this.str.toString());
		this.clone_help(clone);
		clone.font = this.font;
		clone.fontSize = this.fontSize;
		clone.height = this.height;
		clone.width = this.width;
		clone.metrics = this.metrics;
		
		return clone;
	}
}
